﻿using NDK.Module.BLL;
using NDK.Module.Model;
using NDK.Motion.BLL;
using NDK.Motion.MachineManager;
using NDK.Motion.MachineResources;
using NDK.Motion.Monitor;
using NDK.Motion.StationLogic;
using NDK.Utils;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using static NDK.Module.Model.Common;

namespace NDK.Module.StationLogic
{
    [Monitor(Description = "PPG平台工位")]
    public class PPG : StationLogicBase
    {
        #region 通用
        //记录当前步骤，用于步骤变化的比较
        private StationStep _curStep = StationStep.WaitMacInit;
        //对外提供工位的步骤变化事件
        public override event PropertyChangedEventHandler PropertyChanged;
        //对外提供唯一实例
        public static PPG Instance = new PPG();
        //私有化的构造函数
        private PPG() : base()
        {
            Name = "PPG平台";
        }
        //步骤字段、属性
        private StationStep _step = StationStep.WaitMacInit;
        [Monitor(Description = "当前步骤")]
        public StationStep Step
        {
            get
            {
                return _step;
            }
            set
            {
                if (_curStep != value)
                {
                    _step = value;
                    _curStep = value;
                    FileUtils.WriteLogToTxt($"{Step.ToString()}  CT:{Math.Round((double)swStepTime.ElapsedMilliseconds / 1000, 3)}s", logFold, logBaseInfo, isWriteLog);
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(value.ToString()));
                    swStepTime.Restart();
                }
            }
        }
        #endregion

        #region 变量
        public bool 告知中转平台允许放料 { set; get; }
        public bool 告知搬运平台允许到接料位 { set; get; }
        public bool 告知搬运平台允许接料 { set; get; }
        public bool 告知中转GRR物料放料完成 { set; get; }
        #endregion

        /// <summary>
        /// 工站初始化
        /// </summary>
        public override void Init()
        {
            base.Init();
            Step = StationStep.WaitMacInit;
            logBaseInfo = "PPG平台";
            ListVacuum = new List<OutputSetting>() { Machine.DicOutputIO["PPG平台真空吸"] };
            ListCylinder = new List<ICylinder>() { Machine.DicDriveCylinder["PPG气缸"] };
            SNCode1 = string.Empty;
            LocalGRRCount = 0;
            告知中转平台允许放料 = false;
            告知搬运平台允许到接料位 = false;
            告知搬运平台允许接料 = false;
            告知中转GRR物料放料完成 = false;
        }

        /// <summary>
        /// 工站动作流程
        /// </summary>
        /// <param name="mode"></param>
        public override void ActionProcess()
        {
            try
            {
                switch (Step)
                {
                    case StationStep.WaitMacInit:

                        Step = StationStep.Start;
                        break;
                    case StationStep.Start:
                        if (PublicMethod.OffVacuum(ListVacuum) && PublicMethod.HomeCylinder(ListCylinder) && MotionControl.AxesMove(Machine.DicPos[Name]["接料位"]))
                        {
                            告知中转平台允许放料 = true;
                            Step = StationStep.等待放料完成;
                        }
                        break;
                    case StationStep.等待放料完成:
                        if (TransitPlatform.Instance.告知PPG放料完成)
                        {
                            SNCode1 = TransitPlatform.Instance.SNCode1;
                            TransitPlatform.Instance.告知PPG放料完成 = false;
                            Step = StationStep.移动到PPG量测位;
                        }
                        break;
                    case StationStep.移动到PPG量测位:
                        if (MotionControl.AxesMove(Machine.DicPos[Name]["PPG量测位"]))
                        {
                            if (!屏蔽PPG && StationManager.MachineProductionMode != RunningModeEnum.EmptyMode)
                            {
                                if (PublicMethod.WorkCylinder(ListCylinder))
                                {
                                    PublicMethod.Delay(PPG保压时间);
                                    Step = StationStep.PPG量测;
                                }
                            }
                            else
                            {
                                Step = StationStep.气缸上升;
                            }
                        }
                        break;
                    case StationStep.PPG量测:
                        double value = 9999;
                        if (Line == "右")
                        {
                            value = Machine.PPG.Read("01") + PPGOffset;
                        }
                        else
                        {
                            if (!GetPPGValue())
                            {
                                if (AlarmPause("测载具1PPG超时", $"测载具1PPG超时,请检查TCP通讯是否异常", "点击确定，再试一次；点击取消，继续运行", "再试一次", "继续运行") == DialogResult.OK)
                                    break;
                            }
                            value = StationTCP.PPGValue;
                        }
                        DataItem dataItem = new DataItem() { ID = 0, Name = PPGName, Value = value };
                        Machine.DicLocalData[SNCode1].MeasureData.Add(dataItem);
                        Step = StationStep.气缸上升;
                        break;
                    case StationStep.气缸上升:
                        if (PublicMethod.HomeCylinder(ListCylinder))
                        {
                            if (StationManager.MachineProductionMode != RunningModeEnum.GRRMode)
                                告知搬运平台允许到接料位 = true;
                            Step = StationStep.移动到出料位;
                        }
                        break;
                    case StationStep.移动到出料位:
                        if (MotionControl.AxesMove(Machine.DicPos[Name]["出料位"]))
                        {
                            Step = StationStep.等待算法完成;
                        }
                        break;
                    case StationStep.等待算法完成:
                        if (StationManager.MachineProductionMode != RunningModeEnum.EmptyMode)
                        {
                            swStepSplitTime.Restart();
                            if (!Task.WaitAll(Machine.DicLocalData[SNCode1].tasks.ToArray(), TimeSpan.FromSeconds(10)))
                            {
                                if (MessageBox.Show($"算法超时异常:{SNCode1} 请看界面下方消息框分析问题\r\n点击确定，再试一次；点击取消，继续运行", "算法超时", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) == DialogResult.OK)
                                    break;
                            }
                            PublicMethod.writeLog($"到PPG等待算法时间 {Math.Round((double)(swStepSplitTime.ElapsedMilliseconds / 1000), 3)}", "PPG单个分解时间");
                            Task TaskRunData = Task.Run(new Action(() =>
                            {
                                Machine.DicLocalData[SNCode1].Result = ProcessData.PrcessData(Machine.DicLocalData[SNCode1]);
                            }));
                            Machine.DicLocalData[SNCode1].tasks.Add(TaskRunData);
                        }
                        Step = StationStep.GRR模式判断;
                        break;
                    case StationStep.GRR模式判断:
                        if (StationManager.MachineProductionMode == RunningModeEnum.GRRMode)
                        {
                            LocalGRRCount++;
                            if (LocalGRRCount == GRR循环次数)
                            {
                                告知搬运平台允许到接料位 = true;
                                LocalGRRCount = 0;
                            }
                            else
                            {
                                Step = StationStep.GRR物料到中转放料;
                                break;
                            }
                        }
                        告知搬运平台允许接料 = true;
                        Step = StationStep.等待物料取走;
                        break;
                    case StationStep.等待物料取走:
                        if (CarryPlatform.Instance.告知PPG接料完成)
                        {
                            CarryPlatform.Instance.告知PPG接料完成 = false;
                            Step = StationStep.End;
                        }
                        break;
                    case StationStep.GRR物料到中转放料:
                        if (MotionControl.AxesMove(Machine.DicPos[Name]["接料位"]))
                        {
                            if (PublicMethod.WorkCylinder(TransitPlatform.Instance.ListCylinder) && PublicMethod.OpenVacuum(TransitPlatform.Instance.ListVacuum) && PublicMethod.OffVacuum(ListVacuum, false))
                            {
                                if (Machine.DicLocalData.ContainsKey(SNCode1))
                                    Machine.DicLocalData.TryRemove(SNCode1, out MeasureProduct measureProduct);
                                Step = StationStep.GRR物料放料完成;
                            }
                        }
                        break;
                    case StationStep.GRR物料放料完成:
                        Thread.Sleep(200);
                        if (PublicMethod.HomeCylinder(TransitPlatform.Instance.ListCylinder))
                        {
                            PublicMethod.OffVacuum(ListVacuum);
                            告知中转GRR物料放料完成 = true;
                            Step = StationStep.End;
                        }
                        break;
                    case StationStep.End:
                        Step = StationStep.WaitMacInit;
                        break;
                }
            }
            catch (Exception ex)
            {
                UILog_Error($"[ {logBaseInfo} ActionProcess Thread ERROR] {ex.Message}");
                if (AlarmPause(logBaseInfo, $"当前状态:{Step} 报警异常:{ex.Message}", "点击确定，再试一次；点击取消，继续运行", "再试一次", "继续运行") == DialogResult.OK)
                {

                }
            }
        }

        public override void EmptyActionProcess()
        {
            ActionProcess();
        }

        public override void GRRActionProcess()
        {
            ActionProcess();
        }

        bool GetPPGValue()
        {
            StationTCP.PPGValue = 9999;
            StationTCP.SendStr_ClientComputer($"PPG,1");
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Reset();
            while (StationTCP.PPGValue == 9999)
            {
                if (stopwatch.ElapsedMilliseconds > 2000)
                    return false;
            }
            return true;
        }

        /// <summary>
        /// 工位步骤定义
        /// </summary>
        public enum StationStep
        {
            /// <summary>
            /// 等待机台初始化
            /// </summary>
            [Description("等待机台初始化")]
            WaitMacInit,
            [Description("开始")]
            Start,
            等待放料完成,
            移动到PPG量测位,

            PPG量测,
            气缸上升,
            移动到出料位,
            等待算法完成,
            等待物料取走,
            GRR模式判断,
            GRR物料到中转放料,
            GRR物料放料完成,
            [Description("工站完成")]
            End,
        }
    }
}
